package com.pig.config.watcher;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author by 李志伟
 * Create Date: 2019/5/30 2:01
 * Description:
 */
public class ConfigWatcher {

    private static final Logger logger = LoggerFactory.getLogger(ConfigWatcher.class);

    private Map<String, IParse> fileNameProcessMap = new HashMap<>();
    private WatchService watchService;
    private Path path;
    private URL url;

    public void init() {
        logger.info("启动配置文件监控器");
        try {
            watchService = FileSystems.getDefault().newWatchService();
            url = ConfigWatcher.class.getResource("/config/");
            path = Paths.get(url.toURI());
            path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);

            initFiles();

        } catch (Exception e1) {
            e1.printStackTrace();
        }

        /**
         * 启动监控线程
         */
        Thread watchThread = new Thread(new WatchThread());
        watchThread.setDaemon(false);
        watchThread.start();

        /**注册关闭钩子*/
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                watchService.close();
            } catch (IOException e) {
                logger.error("关闭出错", e);
            }
        }));
    }

    private void initFiles() {
        Set<Map.Entry<String, IParse>> entries = fileNameProcessMap.entrySet();
        for (Map.Entry<String, IParse> entry : entries) {
            String fileName = entry.getKey();
            readFile(fileName);
        }
    }

    private void readFile(String fileName) {
        try {
            // 通过输入缓冲流进行读取配置文件
            File file = new File(new URI(url.toString() + fileName));
            String fileContent = FileUtils.readFileToString(file, "utf-8");
            IParse bean = fileNameProcessMap.get(fileName);
            bean.parseContent(fileContent);
            Object o = bean.get();
            logger.info("o={}", o);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public class WatchThread implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    // 尝试获取监控池的变化，如果没有则一直等待
                    WatchKey watchKey = watchService.take();
                    for (WatchEvent<?> event : watchKey.pollEvents()) {
                        String editFileName = event.context().toString();
                        Set<Map.Entry<String, IParse>> entries = fileNameProcessMap.entrySet();
                        for (Map.Entry<String, IParse> entry : entries) {
                            String fileName = entry.getKey();
                            if (fileName.equals(editFileName)) {
                                logger.info("监听到文件内容变化，fileName={}", fileName);
                                readFile(fileName);
                            }
                        }
                    }
                    watchKey.reset();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public Map<String, IParse> getFileNameProcessMap() {
        return fileNameProcessMap;
    }

    public void setFileNameProcessMap(Map<String, IParse> fileNameProcessMap) {
        this.fileNameProcessMap = fileNameProcessMap;
    }

    public static void main(String[] args) {
        ConfigWatcher configWatcher = new ConfigWatcher();
        configWatcher.init();
    }
}
